'''
Created on Aug 4, 2011

@author: bstar
'''
from twisted.web import server
from zope.interface import implements
from dopplershift.backend.frontends.default import IDSBackendFrontend, DefaultBackendFrontend
from twisted.plugin import IPlugin
from dopplershift.core.plugins.interfaces import IDSPlugin
from twisted.internet import reactor
from dopplershift.core.containers.mediator import getMediator
from twisted.web.resource import Resource
from routes.mapper import Mapper
from dopplershift.collector.exc import Http404
from dopplershift.backend.frontends.http import DEFAULT_AUTH_COOKIE_ID
from twisted.web.server import NOT_DONE_YET

class DefaultResource(Resource):
    isLeaf = True
    _url = None
    def __init__(self, frontend):
        self._frontend = frontend
    def rendering(self, request):
        try:
            res = self._frontend.getController(request)
        except Http404 as e:
            request.setResponseCode(404)
            return ""
        return res
    def _authenticated(self, session, request):
        request.SESSION = session
        self.rendering(request)
    def _unauthenticated(self, err, request):
        self.rendering(request)
    def _authenticate(self, request):
        request.SESSION = None    
        d = self._authBackend.authenticate(request.getCookie(self._authCookie))
        d.addCallbacks(
                       self._authenticated, 
                       errback=self._unauthenticated, 
                       callbackArgs=[request], 
                       errbackArgs=[request])
        return NOT_DONE_YET
    def render_GET(self, request):
        return self.rendering(request)
    def render_POST(self, request):
        return self.rendering(request)

class RoutesFrontend(DefaultBackendFrontend):
    implements(IPlugin, IDSPlugin, IDSBackendFrontend)
    name = "http"
    controllers = 'backends.handlers.http'
    def configure(self, config):
        self._config = config
        self._port = int(config.get('http_backend_port'))
        self._pf = getMediator().get("PluginsFactory")
        self.loadsPlugins()
        self._mapper = Mapper()
        for url in self._config.xpath('''/*/routes/route/@url'''):
            self._mapper.connect("route", url)
        resource = DefaultResource(self)
        site = server.Site(resource)
        reactor.listenTCP(
                          self._port,
                          site
                          )        
        
    def loadsPlugins(self):
        self._pf.build(self.controllers, allEnableds=True)
    def getController(self, request):
        url = '/%s'%('/'.join(request.postpath))
        request.matched = self._mapper.match(url)
        if request.matched is None or 'action' not in request.matched or 'view' not in request.matched:
            raise Http404("Not found action or view in matched params")
        try:
            controller = self._pf.get(request.matched['action'], self.controllers)
        except KeyError:
            raise Http404("Not found controller class by action in plugins dir")
        res = controller(request)
        if res is None: return NOT_DONE_YET
        return res